package jasongarrett.spida;

import java.io.IOException;
import java.util.List;

import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.Invocation;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.GenericType;
import javax.ws.rs.core.MediaType;

import org.glassfish.jersey.jackson.JacksonFeature;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;

/**
 * interacts with Spida Software's "Apply" application
 * @see http://www.spidasoftware.com/apply
 */
public class SpidaService implements JobApplicationService
{
	private String baseURI = "http://www.spidasoftware.com/apply";
	
	@Override
	public List<Job> getJobs() throws JsonParseException, JsonMappingException, IOException
	{
		Client client = null;
		try
		{
			client = getClient();
			WebTarget jobsTarget = getJobsTarget(client);
			Invocation.Builder builder = jobsTarget.request(MediaType.APPLICATION_JSON);
			List<Job> jobs = builder.get(new GenericType<List<Job>>() {});
			return jobs;
		}
		finally
		{
			close(client);
		}
	}
	
	@Override
	public String createApplication(Application application) throws JsonProcessingException
	{
		Client client = null;
		try
		{
			client = getClient();
			WebTarget applicationsTarget = getApplicationsTarget(client);
			Invocation.Builder builder = applicationsTarget.request(MediaType.APPLICATION_JSON);
			
			// there *has* to be a way to automatically turn the Application into json 
			//   instead of using this ApplicationJSONConverter
			Application submittedApplication = 
					builder.post(Entity.json(ApplicationJSONConverter.jsonFromApplication(application)), Application.class);
			
			return submittedApplication.get_id();
		}
		finally
		{
			close(client);
		}
	}
	
	@Override
	public void deleteApplication(String applicationId)
	{
		Client client = null;
		try
		{
			client = getClient();
			WebTarget applicationsTarget = getApplicationsTarget(client);
			WebTarget deleteApplicationTarget = applicationsTarget.path("{applicationId}");
			Invocation.Builder builder = 
					deleteApplicationTarget.resolveTemplate("applicationId", applicationId).request(MediaType.APPLICATION_JSON);
			builder.delete();
		}
		finally
		{
			close(client);
		}
	}
	
	@Override
	public Application getApplication(String applicationId) throws Exception
	{
		Client client = null;
		try
		{
			client = getClient();
			WebTarget applicationsTarget = getApplicationsTarget(client);
			WebTarget getApplicationTarget = applicationsTarget.path("{applicationId}");
			Invocation.Builder builder = 
					getApplicationTarget.resolveTemplate("applicationId", applicationId).request(MediaType.APPLICATION_JSON);
			Application application = builder.get(Application.class);
			return application;
		}
		finally
		{
			close(client);
		}
	}
	
	private Client getClient()
	{
		return ClientBuilder.newBuilder().register(JacksonFeature.class).build();
	}
	
	private WebTarget getJobsTarget(Client client)
	{
		return client.target(baseURI).path("jobs");
	}
	
	private WebTarget getApplicationsTarget(Client client)
	{
		return client.target(baseURI).path("applications");
	}
	
	private void close(Client client)
	{
		try
		{
			if(client != null)
			{
				client.close();
			}
		}
		catch(Exception e)
		{
			// consume;
		}
	}
}
